﻿#include "app.h"
#define CLS() while (getchar() != '\n');
size_t SZ = sizeof(Info);
int FLAG = 0;//用来判断是否已经初始化
//struct PersonInfo data[1000] = { 0 };
//char date[1000][50] = { 0 };
Info** PX = NULL;//最后觉得还是用全局px更好 否则在show_all函数中不管是否初始化都需要再初始化一遍 因为show_all是
size_t NUM = 0;//最后一个位置

//主菜单不好传参


void move_key(char* a, const char* b)
{
	assert(a && b);
	while (*(a++) = *(b++));
}
void init()
{
	Info** px = (Info**)calloc(sizeof(Info*), 1);
	assert(px);
	printf("初始化数据中!当前进度:\n");
	FILE* pf = fopen("PersonInfo.txt", "r");
	if (pf == NULL)
	{
		printf("核心文件不存在，您可以新增一个联系人，来创建文件!\n");
		//fclose(pf);
		return;
	}
	int i = 0;
	char mystring[MAX_NO + MAX_NAME + MAX_DATE + MAX_OFFICE + 
		MAX_OFFICEPHONE + MAX_PHONENUM + MAX_TYPE + MAX_SEX +
		MAX_LASTDATE + MAX_ADDRESS + 50] = { 0 };
	while (fgets(mystring, MAX_NO + MAX_NAME + MAX_DATE + MAX_OFFICE +
		MAX_OFFICEPHONE + MAX_PHONENUM + MAX_TYPE + MAX_SEX +
		MAX_LASTDATE + MAX_ADDRESS + 50, pf) != NULL)
	{
		memset(px + i, 0, SZ);//这个memset是必须要的 因为realloc会把这块新加的空间初始化为不知道什么值
		printf("\r%.2f%c", (i * 1.0) / 10, '%');
		//Sleep(1);//好玩的 太快了
		int j = 0;
		int tmp = 0;
		int code = mystring[j] - '0';
		j += 2;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_NO; tmp++, j++)
			px[i]->_no[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_NAME; tmp++, j++)
			px[i]->_name[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_DATE; tmp++, j++)
			px[i]->_date[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_OFFICE; tmp++, j++)
			px[i]->_office[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_OFFICEPHONE; tmp++, j++)
			px[i]->_officephone[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_PHONENUM; tmp++, j++)
			px[i]->_phonenum[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_TYPE; tmp++, j++)
			px[i]->_type[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_SEX; tmp++, j++)
			px[i]->_type[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != ';' && tmp < MAX_LASTDATE; tmp++, j++)
			px[i]->_type[tmp] = mystring[j] + code;
		j++;
		for (tmp = 0; mystring[j] != '\n' && tmp < MAX_ADDRESS; tmp++, j++)
			px[i]->_type[tmp] = mystring[j] + code;
		Info** ptx = (Info**)realloc(px, ((size_t)i + 2) * sizeof(Info*));
		if (ptx != NULL)
		{
			px = ptx;
			//px = px ;
		}
		else
		{
			printf("内存不够!\n");
			return;
		}
		ptx = NULL;
		i++;
	}
	fclose(pf);
	NUM = i;
	printf("\r100.00%c\n", '%');
	FLAG = 1;
	PX = px;
}
void check()
{
	init();
	int input = 0;
	
	do
	{
		printf("您想通过何种方式查找指定联系人?\n1.姓名 2.电话 3.地址 4.添加该联系人的时间 0.退出查找\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			check_solve(1);
			break;
		case 2:
			check_solve(2);
			break;
		case 3:
			check_solve(3);
			break;
		case 4:
			check_solve(4);
			break;
		case 0:
			return;
		default:
			printf("选择错误!");
			break;
		}
	} while (input);
}
void check_solve(int flag)
{
	int result[10] = { 0 };//将结果放置 担心有重名
	int j = 0;
	int k = 0;//与result有关
	int like = 0;
	int like_l = 0;
	if (flag == 1)
	{
		char name[MAX_NAME] = { 0 };
		printf("请输入姓名:");
		scanf("%s", &name);
		for (j = 0; j < NUM; j++)
		{
			if (strcmp(PX[j]->_name, name) == 0)
			{
				result[k] = j;
				k++;
			}
			else
			{
				int x = 0;
				int tmp = 0;
				for (x = 0; x < MAX_NAME; x++)
				{
					if (name[x] == PX[j]->_name[x] && name[x] != '\0')
						tmp++;
				}
				if (tmp > like)
				{
					like = tmp;
					like_l = j;
				}
			}
		}
	}
	else if (flag == 2)
	{
		char num[MAX_PHONENUM] = { 0 };
		printf("请输入电话:");
		scanf("%s", &num);
		for (j = 0; j < NUM; j++)
		{
			if (strcmp(PX[j]->_phonenum, num) == 0)
			{
				result[k] = j;
				k++;
			}
			else
			{
				int x = 0;
				int tmp = 0;
				for (x = 0; x < MAX_PHONENUM; x++)
				{
					if (num[x] == PX[j]->_phonenum[x] && num[x] != '\0')
						tmp++;
				}
				if (tmp > like)
				{
					like = tmp;
					like_l = j;
				}
			}
		}
	}
	else if (flag == 3)
	{
		char add[MAX_ADDRESS] = { 0 };
		printf("请输入地址:");
		scanf("%s", &add);
		for (j = 0; j < NUM; j++)
		{
			if (strcmp(PX[j]->_address, add) == 0)
			{
				result[k] = j;
				k++;
			}
			else
			{
				int x = 0;
				int tmp = 0;
				for (x = 0; x < MAX_ADDRESS; x++)
				{
					if (add[x] == PX[j]->_address[x] && add[x] != '\0')
						tmp++;
				}
				if (tmp > like)
				{
					like = tmp;
					like_l = j;
				}
			}
		}
	}
	else if (flag == 4)
	{
		char datet[50] = { 0 };
		printf("请输入时间:");
		scanf("%s", &datet);
		for (j = 0; j < NUM; j++)
		{
			if (strcmp(PX[j]->_lastdate, datet) == 0)
			{
				result[k] = j;
				k++;
			}
			else
			{
				int x = 0;
				int tmp = 0;
				for (x = 0; x < 50; x++)
				{
					if (datet[x] == PX[j]->_lastdate[x] && datet[x] != '\0')
						tmp++;
				}
				if (tmp > like)
				{
					like = tmp;
					like_l = j;
				}
			}
		}
	}
	system("cls");
	if (k == 0)
	{
		printf("---------------------------------------------------------------------------------\n");
		printf("没有找到完全符合您需求的联系人.\n程序猜测您在寻找该位联系人:\n姓名:%s \n电话号码:%s \n住址:%s \n最后一次修改该联系人的时间:%s\n目前序号:%d\n"
			, PX[like_l]->_name, PX[like_l]->_phonenum, PX[like_l]->_address, PX[like_l]->_lastdate, like_l);
		printf("---------------------------------------------------------------------------------\n");
	}
	else
	{
		printf("---------------------------------------------------------------------------------\n");
		printf("找到了 %d 个完全符合的联系人，信息如下:\n", k);
		printf("%-20s%-5s%-20s%-20s%-35s%-s\n", "姓名", "性别", "电话号码", "住址", "添加该联系人的时间", "目前序号");
		for (j = 0; j < k; j++)
		{
			printf("%-20s%-5s%-20s%-20s%-35s%d\n", PX[result[j]]->_name,
				PX[result[j]]->_sex, PX[result[j]]->_phonenum,
				PX[result[j]]->_address, PX[result[j]]->_date, result[j]);
		}
		printf("---------------------------------------------------------------------------------\n");
	}
}

void move(int mode)
{
	printf("请输入该位联系的目前序号(通过查找联系人查询)(如需退出查询，输入1111):");
	int num = 0;
	scanf("%d", &num);
	if (num == 11111)
		return;
	if (FLAG == 0)
		init();
	if (mode == 1)
	{
		printf("您目前在修改联系人 %s 的信息\n", PX[num]->_name);
		printf("以下信息如不需修改则输入quit\n");
		printf("请输入新名字:");
		char name[MAX_NAME] = { 0 };
		scanf("%s", &name);
		if (strcmp(name, "quit") != 0)
			move_key(PX[num]->_name, name);
		printf("请输入新性别:");
		char sex[MAX_SEX] = { 0 };
		scanf("%s", &sex);
		if (strcmp(sex, "quit") != 0)
			move_key(PX[num]->_sex, sex);
		printf("请输入新电话号码:");
		char num1[MAX_PHONENUM] = { 0 };
		scanf("%s", &num1);
		if (strcmp(num1, "quit") != 0)
			move_key(PX[num]->_phonenum, num1);
		printf("请输入新住址:");
		char add[MAX_ADDRESS] = { 0 };
		scanf("%s", &add);
		if (strcmp(add, "quit") != 0)
			move_key(PX[num]->_address, add);
		int i = 0;
		remove("PersonInfo.txt");
		FILE* pf = fopen("tmp.txt", "w");
		fclose(pf);
		rename("tmp.txt", "PersonInfo.txt");
		for (i = 0; i < NUM; i++)
		{
			// put(PX + i);
		}
		printf("修改成功!\n");
	}
	else if (mode == 2)
	{
		printf("您当前正在删除 %s 的信息，您确定这样做吗？(YES确定，其他退出):", PX[num]->_name);
		char ans[20] = { 0 };
		scanf("%20s", &ans);
		if (strcmp(ans, "YES") != 0)
			return;
		int i = 0;
		remove("PersonInfo.txt");
		FILE* pf = fopen("tmp.txt", "w");
		fclose(pf);
		rename("tmp.txt", "PersonInfo.txt");
		for (i = 0; i < NUM; i++)
		{
			if (i != num)
				put(PX + i);
		}
		printf("删除成功!\n");
	}
	FLAG = 0;
}
void show_all()
{
	int i = 0;
	printf("---------------------------------------------------------------------------------\n");
	printf("所有联系人信息如下:\n");
	printf("%-30s%-30s%-30s%-30s%-30s%-30s%-30s%-30s%-30s%-30s\n", "编号", "姓名", "性别", "生日", "地址", "办公室", "办公电话", "电话号码", "分类", "最后一次修改的时间");
	for (i = 0; i < NUM; i++)
		printf("%-30s%-30s%-30s%-30s%-30s%-30s%-30s%-30s%-30s%-30s\n", PX[i]->_no, PX[i]->_name,
			PX[i]->_sex, PX[i]->_date, PX[i]->_address, PX[i]->_office, PX[i]->_officephone,
			PX[i]->_phonenum, PX[i]->_type, PX[i]->_lastdate);
	printf("---------------------------------------------------------------------------------\n");
}


void _scanf(char* dest, size_t max)
{
	if (max == 1)
	{
		*dest = getchar();
		if (*dest == '\n')
			*dest = '\0';
		return;
	}
	size_t num = 0;
	char tmp = 0;
	while (num < max - 1 && (tmp = getchar()) != '\n')
	{
		dest[num] = tmp;
		++num;
	}
	dest[num] = '\0';
}


void Input(char* dest, char* source, size_t max)
{
	do
	{
		printf("请输入%s:", source);
		_scanf(dest, max);
	} while (strcmp(dest, "\0") == 0);
}

void AddNew()
{
	Info* p = (Info*)calloc(1, sizeof(Info));
	assert(p);
	CLS();
	Input(p->_name, "姓名", MAX_NAME);
	Input(p->_sex, "性别", MAX_SEX);
	Input(p->_date, "生日", MAX_DATE);
	Input(p->_office, "办公室", MAX_OFFICE);
	Input(p->_officephone, "办公室电话", MAX_OFFICEPHONE);
	Input(p->_phonenum, "电话号码", MAX_PHONENUM);
	Input(p->_type, "类别", MAX_TYPE);
	Input(p->_sex, "地址", MAX_ADDRESS);
	/*char NameTmp[MAX_NAME] = { 0 };
	strcpy(NameTmp, p._name);*/
	//FILE* pf = fopen("PersonInfo.txt", "a");
	/*if (1 == put(&p))
		printf("增加联系人 %s  成功!\n", NameTmp);
	else
		printf("新增失败，发生错误!\n");*/
	PX[NUM++] = p;
}

int put(struct PersonInfo* p)
{
	FILE* pf = fopen("PersonInfo.txt", "a");
	if (pf == NULL)
	{
		printf("发生错误!\n");
		return 0;
	}
	char ltime[50] = { 0 };
	get_time(ltime);
	srand((unsigned)time(NULL));
	int code = rand() % 9 + 1;
	fputc(code + '0', pf);
	fputc(';', pf);
	jiamihejiemi(p->_name, strlen(p->_name), code, 0);
	fputs(p->_name, pf);
	fputc(';', pf);
	jiamihejiemi(p->_sex, strlen(p->_sex), code, 0);
	fputs(p->_sex, pf);
	fputc(';', pf);
	jiamihejiemi(p->_phonenum, strlen(p->_phonenum), code, 0);
	fputs(p->_phonenum, pf);
	fputc(';', pf);
	jiamihejiemi(p->_address, strlen(p->_address), code, 0);
	fputs(p->_address, pf);
	fputc(';', pf);
	jiamihejiemi(ltime, strlen(ltime), code, 0);
	fputs(ltime, pf);
	fputc('\n', pf);
	fclose(pf);
	return 1;
}
void put_time(char** ltime, int time_flag)
{
	**ltime = time_flag / 10 + '0';
	(*ltime)++;
	**ltime = time_flag % 10 + '0';
	(*ltime)++;
	//为什么这里的ltime没有改变 我认为是因为ltime本身传进来还是一个形参 要用二级指针
}
void get_time(char* ltime)
{
	time_t timep;
	struct tm* p;
	time(&timep);
	p = gmtime(&timep);
	int i = 0;
	int year = 1900 + p->tm_year;
	while (year > 0)
	{
		*ltime = (year % (int)pow(10, 4 - i)) / (int)pow(10, 3 - i) + '0';
		ltime++;
		i++;
		year = year % (int)pow(10, 4 - i);
	}
	strcat(ltime, "年");
	ltime += 2;
	char* week[7] = { "星期一","星期二","星期三","星期四","星期五","星期六","星期天" };
	put_time(&ltime, 1 + p->tm_mon);
	strcat(ltime, "月");
	ltime += 2;
	put_time(&ltime, p->tm_mday);
	strcat(ltime, "日");
	ltime += 2;
	strcat(ltime, week[p->tm_wday]);
	ltime += 6;
	put_time(&ltime, p->tm_hour + 8);
	strcat(ltime, "时");
	ltime += 2;
	put_time(&ltime, p->tm_min);
	strcat(ltime, "分");
	ltime += 2;
	put_time(&ltime, p->tm_sec);
	strcat(ltime, "秒");
}
void cls_all()
{
	printf("您当前希望清除所有的联系人，您确定这样做吗？(YES表确定，其他表退出):");
	char ans[20] = { 0 };
	scanf("%s", &ans);
	if (strcmp(ans, "YES") != 0)
		return;
	remove("PersonInfo.txt");
	FILE* pf = fopen("tmp.txt", "w");
	fclose(pf);
	rename("tmp.txt", "PersonInfo.txt");
	printf("清除成功!\n");
}


void only_menu()
{
	printf("-----------------------------------------\n");
	printf("-----          1.增加联系人         -----\n");
	printf("-----          2.查找联系人         -----\n");
	printf("-----          3.修改联系人         -----\n");
	printf("-----          4.显示所有联系人     -----\n");
	printf("-----          5.删除指定联系人     -----\n");
	printf("-----          6.清空所有联系人     -----\n");
	printf("-----          0.退出程序           -----\n");
	printf("-----------------------------------------\n");
}
void menu()
{
	int input = 0;
	Info** tmp = (Info**)calloc(1, sizeof(Info*));
	assert(tmp);
	PX = tmp;
	do
	{
		only_menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1://增加
			AddNew();
			break;
		case 2://查找
			check();
			break;
		case 3://修改
			move(1);
			break;
		case 4://显示所有
			show_all();
			break;
		case 5://删除指定
			move(2);
			break;
		case 6://清空
			cls_all();
			break;
		case 0://退出
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
}


void jiamihejiemi(char* p, size_t sz, int code, int flag)//0ʾ 1 ʾ
{
	assert(p);
	if (flag == 0)
		while (sz > 0)
		{
			*p -= code;
			p++;
			sz--;
		}
	if (flag == 1)
		while (sz > 0)
		{
			*p += code;
			p++;
			sz--;
		}
}